﻿#region Header

/*
Remote views based on linq
By

Pascal Hauser 
Dipl. Ing. in Informatik, Hochschule für Technik Rapperswil, 2006
Master Thesis, Hochschule für Technik Rapperswil, 2008-2010

and

Raphael Gfeller
Dipl. Ing. in Informatik, Hochschule für Technik Rapperswil, 2006
Master Thesis, Hochschule für Technik Rapperswil, 2008-2010

*/

#endregion

#region Usings

using System;
using System.Collections;
using InterLinq.Types;
using Sebarf.Core.Interfaces;
using Sebarf.Services.Interfaces;
using Sebastof.Services.Interfaces;
using Utils;

#endregion

namespace Sebastof.ProcessChains.ProcessSteps {
	/// <summary>
	/// This is another processing step (for collections).
	/// If the objects with the attached metadata id were already loaded once, the previously loaded objects will be returned.
	/// So loading the same objects twice will return the identical (reference identical) objects.
	/// </summary>
	public class UseCachedCollectionStep : ProcessStep<CollectionTransporter> {
		#region Public Properties

		[ServiceRequest]
		public ICachedDataRegistrationService CachedDataRegistrationService { get; set; }

		[ServiceRequest]
		public ICachedDataLocatorService CachedDataLocatorService { get; set; }

		[ServiceRequest]
		private IObjectSynchronisationService DatahandlerService { get; set; }

		#endregion

		#region Public Methods

		public UseCachedCollectionStep(IServiceLocatorService locator) {
			CachedDataLocatorService = locator.GetRegisteredService<ICachedDataLocatorService>();
			CachedDataRegistrationService = locator.GetRegisteredService<ICachedDataRegistrationService>();
		}

		public UseCachedCollectionStep() {
		}

		/// <summary>
		/// Replaces the objects in the collection with the previously loaded ones (if they exists)
		/// </summary>
		/// <param name="toProcess"></param>
		/// <returns></returns>
		protected override CollectionTransporter OnProcess(CollectionTransporter toProcess) {
			if (toProcess.Values is String) {
				return toProcess;
			}
			if (!(toProcess.Values is Array || toProcess.Values is IList)) {
				throw new NotSupportedException();
			}

			if (toProcess.Values is Array) {
				for (int i = 0; i < ((Array)toProcess.Values).Length; i++) {
					Object item = ((Array)toProcess.Values).GetValue(i);

					string key = toProcess.TransferedMetadata.GetMetadata(item, "UniqueIdentifier", Guid.NewGuid().ToString());
					//if (!CachedDataLocatorService.ContainsKey(key)) {
					//    // insert entry into the cache
					//    CachedDataRegistrationService.AddOrUpdateCachedValue(key, item);
					//}
					//else {
					//    // load entry from cache
					//    object storedItem = CachedDataLocatorService.GetCachedData<Object>(key);

					//}
					((Array)toProcess.Values).SetValue(
						DatahandlerService.MergeObject(key,
														!CachedDataLocatorService.ContainsKey(key)
															? null
															: CachedDataLocatorService.GetCachedData<Object>(key), item), i);
				}
			}
			else if (toProcess.Values is IList) {
				for (int i = 0; i < ((IList)toProcess.Values).Count; i++) {
					Object item = ((IList)toProcess.Values)[i];

					var key = toProcess.TransferedMetadata.GetMetadata<String>(item, "UniqueIdentifier");
					//if (!CachedDataLocatorService.ContainsKey(key)) {
					//    // insert entry into the cache
					//    CachedDataRegistrationService.AddOrUpdateCachedValue(key, item);
					//}
					//else {
					//    // load entry from cache
					//    object storedItem = CachedDataLocatorService.GetCachedData<Object>(key);
					((IList)toProcess.Values)[i] = DatahandlerService.MergeObject(key,
																					 !CachedDataLocatorService.ContainsKey(key)
																						? null
																						: CachedDataLocatorService.GetCachedData<Object>
																							(key), item);
					//	}
				}
			}
			return toProcess;
		}

		#endregion
	}
}